﻿#include "IPluginOperator.h"
#include "IPluginDialog.h"

#include <QMetaProperty>
#include <QTranslator>
#include <QApplication>
#include <QTime>
#include <QtConcurrent>
#include <QFuture>
#include <QFutureWatcher>

#include "PluginContainerWidget.h"
#include "IAlgorithmPluginOperator.h"
#include "IAlgorithmPluginParam.h"
#include "AbstractEntity.h"
#include "IFlowTreeManager.h"
#include "ISignalBridge.h"


namespace CVV
{

namespace Interface
{

QString IPluginOperator::s_localName = "";
IPluginOperator::IPluginOperator(QObject *parent)
    : QObject(parent)
{
}

IPluginOperator::~IPluginOperator()
{

}

bool IPluginOperator::init(const QString &flowId, const QString& cellId, const QDomElement &cellDom)
{
    if(m_flowCellDialogs.contains(flowId))
    {
        if(m_flowCellDialogs[flowId].contains(cellId))
        {
            QDomElement pluginDom = cellDom.firstChildElement("plugininfo");
            if (pluginDom.isNull())
            {
                return false;
            }
            bool bIsModelData = (cellDom.attribute("isModelData") == "true");
            initCellParam(pluginDom, flowId, cellId, bIsModelData);
            initCellAlgorithmParam(pluginDom, flowId, cellId);

            // 更新dom
            m_flowCellDialogs[flowId][cellId]->updatedDom();
            m_flowCellDialogs[flowId][cellId]->init();
        }
    }
    return true;
}

IPluginParam IPluginOperator::showFlowCellDialog(const QString &pluginCode, const QString &flowId, const QString &cellId)
{
    IPluginParam param;
    CVV::Interface::IPluginOperator * opt=dynamic_cast<CVV::Interface::IPluginOperator *>
            (CVV::Infrastructure::ExtensionSystem::PluginManager
             ::getObjectByName(pluginCode));

    if(opt)
    {
        std::shared_ptr<CVV::Interface::IPluginDialog> dialog = opt->flowCellDialogs()[flowId][cellId];
        if(dialog)
        {
            // 更新dom
            dialog->updatedDom();
            dialog->init();
            PluginContainerWidget *m_pluginContainWigdet = new PluginContainerWidget(dialog.get());
            connect(dialog.get(), &IPluginDialog::sigClose, m_pluginContainWigdet, &PluginContainerWidget::close);
            connect(dialog.get(), &IPluginDialog::sigRunTime, m_pluginContainWigdet, &PluginContainerWidget::sltUpdateRuntime);
//            m_pluginContainWigdet->setPluginDialog(dialog);
            m_pluginContainWigdet->setRuntimeVisible(dialog->runtimeIsVisible());
            param = *(dialog->getPluginParam());
            m_pluginContainWigdet->sltUpdateRuntime(param.getT_elapsedTime());
            if( (0 == param.getT_code().compare("CategoryModel")) ||
                (param.getT_code().indexOf("ClassifyCheck") >= 0) ||
                (param.getT_code().indexOf("TargetCheck") >= 0))
            {
//                m_pluginContainWigdet->showMaximized();   //王俊学：我的模块需要最大化
                m_pluginContainWigdet->setWindowState(m_pluginContainWigdet->windowState() ^ Qt::WindowMaximized);
            }
            m_pluginContainWigdet->exec();
            param = *(dialog->getPluginParam());
//            disconnect(dialog, &IPluginDialog::sigClose, m_pluginContainWigdet, &PluginContainerWidget::close);
//            disconnect(dialog, &IPluginDialog::sigRunTime, m_pluginContainWigdet, &PluginContainerWidget::sltUpdateRuntime);
        }
    }

    return  param;
}


QList<FlowCellParam> IPluginOperator::createFlowCellDialog(const QString &pluginCode,
                                                           const QString &flowId,
                                                           const QString &cellId,
                                                           const QString &cellTitle,
                                                           const QStringList &lstDefectPinYinCode,
                                                           const QString &subflowFileName,
                                                           bool bIsExamples)
{
    QList<FlowCellParam> flowCellParams;
    CVV::Interface::IPluginOperator * oper = dynamic_cast<CVV::Interface::IPluginOperator *>
            (CVV::Infrastructure::ExtensionSystem::PluginManager
             ::getObjectByName(pluginCode));
    if(oper)
    {
        oper->createFlowCell(pluginCode, flowId, cellId, cellTitle);
        std::shared_ptr<CVV::Interface::IPluginDialog> dlg = oper->flowCellDialogs()[flowId][cellId];
        if (dlg)
        {
            IPluginParam* pParam = dlg->getPluginParam();
            if (pParam)
            {
                pParam->setIsExamples(bIsExamples);
                if (pluginCode == "Subprocess")     // 子流程
                {
                    pParam->setProperty("SubprocessFileName", subflowFileName);
                    dlg->setSubprocessFlowCellParam(gFlowTreeManager->getFlowCellParamByFile(subflowFileName));
                }
            }

            dlg->setDefectPinYinCode(lstDefectPinYinCode);
            dlg->changeLanguage(CVV::Interface::ISignalBridge::instance()->getLocale());
            flowCellParams = dlg->getFlowCellParam();

            // 算法参数
            createAlgorithmParam(pluginCode, flowId, cellId);
        }

    }
    return flowCellParams;
}

QList<FlowCellParam> IPluginOperator::updateSubProcessFilePath(const QString flowId, const QString cellId, const QString filePath, const QString title)
{
    QList<FlowCellParam> flowCellParams;
    QString code = "Subprocess";
    CVV::Interface::IPluginOperator * oper = dynamic_cast<CVV::Interface::IPluginOperator *>
            (CVV::Infrastructure::ExtensionSystem::PluginManager
             ::getObjectByName(code));
    if(oper)
    {
        std::shared_ptr<CVV::Interface::IPluginDialog> dlg = oper->flowCellDialogs()[flowId][cellId];
        if (dlg)
        {
            IPluginParam* pParam = dlg->getPluginParam();
            if (pParam)
            {
                pParam->setProperty("SubprocessFileName", filePath);
                pParam->setProperty("Title", title);
                dlg->setSubprocessFlowCellParam(gFlowTreeManager->getFlowCellParamByFile(filePath));
                flowCellParams = dlg->getFlowCellParam();
            }
        }
    }
    return flowCellParams;
}

bool IPluginOperator::removeFlowCellDialog(const QString &flowId, const QString &cellId)
{
    if(m_flowCellDialogs.contains(flowId))
    {
        if(m_flowCellDialogs[flowId].contains(cellId))
        {
             std::shared_ptr<IPluginDialog> pDlg =  m_flowCellDialogs[flowId].take(cellId);
             if (pDlg)
             {
                 pDlg.reset();
                 pDlg = nullptr;
             }

             return true;
        }
    }

    return  false;
}

bool IPluginOperator::removeFlowDialog(const QString &flowId)
{
    if(m_flowCellDialogs.contains(flowId))
    {
        QMap<QString, std::shared_ptr<IPluginDialog>> mapDialog = m_flowCellDialogs.take(flowId);
        mapDialog.clear();

        return true;
    }

    return false;
}


QMap<QString, QMap<QString, std::shared_ptr<CVV::Interface::IPluginDialog>> > IPluginOperator::flowCellDialogs() const
{
    return  m_flowCellDialogs;
}

void IPluginOperator::setflowCellDialogs(const QMap<QString, QMap<QString, std::shared_ptr<CVV::Interface::IPluginDialog>> > &value)
{
    m_flowCellDialogs = value;
}

bool IPluginOperator::run(const QString &flowId, const QString &cellId)
{
    if(m_flowCellDialogs.contains(flowId))
    {
        if(m_flowCellDialogs[flowId].contains(cellId))
        {
            std::shared_ptr<IPluginDialog> plugDialog = m_flowCellDialogs[flowId][cellId];
            if(plugDialog->run())
            {
                 plugDialog->getPluginParam()->setT_status(CVV::Interface::RunStatus::RunSuccessfully);
                 return true;
            }
            else
            {
                 plugDialog->getPluginParam()->setT_status(CVV::Interface::RunStatus::RunError);
                 return false;
            }
        }
    }
    return  false;
}

void IPluginOperator::updateFlowTree(const QString &flowId, const QString &cellId, const QMap<QString,FlowTree> &flowTree)
{
    if(m_flowCellDialogs.contains(flowId))
    {
        if(m_flowCellDialogs[flowId].contains(cellId))
        {
           m_flowCellDialogs[flowId][cellId]->setFlowTree(flowTree);
        }
    }
}

bool IPluginOperator::run(const QString &pluginCode, const QString &flowId, const QString &cellId)
{
    CVV::Interface::IPluginOperator * opt=dynamic_cast<CVV::Interface::IPluginOperator *>
            (CVV::Infrastructure::ExtensionSystem::PluginManager
             ::getObjectByName(pluginCode));

    if(opt != nullptr){
       return opt->run(flowId,cellId);
    }
    return  false;
}

bool IPluginOperator::init(const QString &pluginCode, const QString &flowId, const QString &cellId, const QDomElement &cellDom)
{
    CVV::Interface::IPluginOperator *opt = dynamic_cast<CVV::Interface::IPluginOperator *>
            (CVV::Infrastructure::ExtensionSystem::PluginManager
             ::getObjectByName(pluginCode));

    if(opt != nullptr){
       return opt->init(flowId, cellId, cellDom);
    }
    return  false;
}

bool IPluginOperator::removeFlowCellDialog(const QString &pluginCode, const QString &flowId, const QString &cellId)
{
    CVV::Interface::IPluginOperator * opt=dynamic_cast<CVV::Interface::IPluginOperator *>
            (CVV::Infrastructure::ExtensionSystem::PluginManager
             ::getObjectByName(pluginCode));

    removeAlgorithmParam(pluginCode, flowId, cellId);
    if(opt != nullptr)
    {
       return opt->removeFlowCellDialog(flowId, cellId);
    }

    return  false;
}

bool IPluginOperator::removeAllFlowDialog(const QString &flowId)
{

    int removeCount = 0;
    for(auto &pluginCell : CVV::Infrastructure::ExtensionSystem::PluginManager::allObjects())
    {
        //耗时操作，不阻塞UI界面
        QCoreApplication::processEvents();
        CVV::Interface::IPluginOperator* opt = dynamic_cast<CVV::Interface::IPluginOperator*>(pluginCell);
        if(opt)
        {
            if(opt->removeFlowDialog(flowId))
            {
                ++removeCount;
            }
        }
        else
        {
            CVV::Interface::IAlgorithmPluginOperator* optAlg = dynamic_cast<CVV::Interface::IAlgorithmPluginOperator*>(pluginCell);
            if (optAlg)
            {
                optAlg->removeAlgorithmParam(flowId);
            }
        }
    }
    qDebug() << __func__ << "Delete dialog count: " << removeCount;

    return  true;
}

void IPluginOperator::removeAlgorithmParam(const QString &pluginCode, const QString &flowId, const QString &cellId)
{
    QString algPluginCode = pluginCode + "Algorithm";
    CVV::Interface::IAlgorithmPluginOperator* opt = dynamic_cast<CVV::Interface::IAlgorithmPluginOperator *>
            (CVV::Infrastructure::ExtensionSystem::PluginManager
             ::getObjectByName(algPluginCode));
    if(opt)
    {
       opt->removeAlgorithmParam(flowId, cellId);
    }
}


bool IPluginOperator::updateFlowTree(const QString &pluginCode, const QString &flowId, const QString &cellId, const QMap<QString, FlowTree> &flowTree)
{
    IPluginParam param;
    CVV::Interface::IPluginOperator * opt=dynamic_cast<CVV::Interface::IPluginOperator *>
            (CVV::Infrastructure::ExtensionSystem::PluginManager
             ::getObjectByName(pluginCode));

    if(opt != nullptr){
       opt->updateFlowTree(flowId,cellId,flowTree);
       return  true;
    }
    return  false;
}

bool IPluginOperator::createDialog(const QString &flowId, const QString &cellId, std::shared_ptr<IPluginDialog> dlg)
{
    if(!m_flowCellDialogs.contains(flowId))
    {
        QMap<QString, std::shared_ptr<CVV::Interface::IPluginDialog>> dialog;
        dialog.insert(cellId, dlg);
        m_flowCellDialogs.insert(flowId, dialog);
    }
    else
    {
        if(!m_flowCellDialogs[flowId].contains(cellId))
        {
            m_flowCellDialogs[flowId].insert(cellId, dlg);
        }
    }

    return  true;
}

bool IPluginOperator::initCellParam(const QDomElement &domEle, const QString &flowId, const QString &cellId, bool isModelData)
{
    if (!m_flowCellDialogs[flowId][cellId])
    {
        return false;
    }

    IPluginParam* param = m_flowCellDialogs[flowId][cellId]->getPluginParam();
    if (!param)
    {
        return false;
    }

    const QMetaObject* metaObj = param->metaObject();
    if (!metaObj)
    {
        return false;
    }

    QDomElement cellParamDomEle = domEle.firstChildElement("cellparam");
    if (cellParamDomEle.isNull())
    {
        return false;
    }

    QMap<QString, QString> pluginMap;
    QMap<QString, QVariant> pluginVariantMap;
    for(int i = 0; i < cellParamDomEle.childNodes().size(); i++)
    {
        auto node = cellParamDomEle.childNodes().at(i);
        if(parserCellParamChildNode(node, pluginVariantMap))
        {
            continue;
        }

        pluginMap.insert(node.nodeName(), node.toElement().attribute("Value"));
    }

    int propertyCnt = metaObj->propertyCount();
    for ( int i = 1; i < propertyCnt; ++i )
    {
        QMetaProperty oneProperty = metaObj->property(i);
        QString properyName = oneProperty.name();
        QString pvalue = pluginMap.value(properyName);
        if(oneProperty.type() == QVariant::PointF)
        {
            QStringList li =  pvalue.split(",");
            if(li.size() != 2)
            {
                continue;
            }
            QPointF point = QPointF(li.first().toFloat(), li.last().toFloat());
            param->setProperty(oneProperty.name(), QVariant::fromValue(point));
        }
        else if(oneProperty.type() == QVariant::RectF)
        {
            QStringList li =  pvalue.split(",");
            if(li.size() != 4)
            {
                continue;
            }

            QRectF rec = QRectF(li.at(0).toFloat(), li.at(1).toFloat(), li.at(2).toFloat(), li.at(3).toFloat());
            param->setProperty(oneProperty.name(), QVariant::fromValue(rec));
        }
        else if(oneProperty.type() == QVariant::StringList)
        {
            QStringList li =  pvalue.split(",");
//            li.removeLast();
            param->setProperty(oneProperty.name(), QVariant::fromValue(li));
        }
        else if(oneProperty.type() == QVariant::Bool)
        {
            bool value = false;
            if(pvalue == "true")
            {
                value = true;
            }
            param->setProperty(oneProperty.name(), QVariant::fromValue(value));
        }
        else if(oneProperty.type() == QVariant::Double)
        {
            float value = pvalue.toDouble();
            param->setProperty(oneProperty.name(), QVariant::fromValue(value));
        }
        else if (oneProperty.type() == QVariant::UserType)
        {
            QVariant var = pluginVariantMap.value(properyName);
            if (var.isValid())
            {
                param->setProperty(oneProperty.name(), var);
            }
        }
        else
        {
            param->setProperty(oneProperty.name(), pvalue);
        }
    }

    // 是否是模板数据
    param->setIsModelData(isModelData);
    return true;
}

bool IPluginOperator::initCellAlgorithmParam(const QDomElement &domEle, const QString &flowId, const QString &cellId)
{
    if (!m_flowCellDialogs[flowId][cellId])
    {
        return false;
    }

    IPluginParam* param = m_flowCellDialogs[flowId][cellId]->getPluginParam();
    if (!param)
    {
        return false;
    }

    IAlgorithmPluginOperator* pAlgOpt = dynamic_cast<IAlgorithmPluginOperator*>(CVV::Infrastructure::ExtensionSystem::PluginManager
            ::getObjectByName(param->getAlgoritmPluginCode()));
    if(!pAlgOpt)        // 没有算法插件
    {
        return false;
    }
    std::shared_ptr<IAlgorithmPluginParam> pAlgParam = pAlgOpt->getAlgorithmPluginParam(flowId, cellId);
    if (!pAlgParam)
    {
        return false;
    }

    const QMetaObject* metaObj = pAlgParam->metaObject();
    if (!metaObj)
    {
        return false;
    }

    QDomElement cellParamDomEle = domEle.firstChildElement("algorithmparam");
    if (cellParamDomEle.isNull())
    {
        return false;
    }

    QMap<QString, QString> pluginMap;
    QMap<QString, QVariant> pluginVariantMap;
    for(int i = 0; i < cellParamDomEle.childNodes().size(); i++)
    {
        auto node = cellParamDomEle.childNodes().at(i);
        if (parserCellAlgorithmParamChildNode(node, pluginVariantMap))
        {
            continue;
        }

        pluginMap.insert(node.nodeName(), node.toElement().attribute("Value"));
    }

    int propertyCnt = metaObj->propertyCount();
    for ( int i = 1; i < propertyCnt; ++i )
    {
        QMetaProperty oneProperty = metaObj->property(i);

        if (oneProperty.type() == QVariant::UserType
                || oneProperty.type() == QVariant::Point)
        {
            QVariant var = pluginVariantMap.value(oneProperty.name());
            if (var.isValid())
            {
                pAlgParam->setProperty(oneProperty.name(), var);
            }
        }
        else if(oneProperty.type() == QVariant::StringList)
        {
            QString properyName = oneProperty.name();
            QString pvalue = pluginMap.value(properyName);
            QStringList li =  pvalue.split(",");
            pAlgParam->setProperty(oneProperty.name(), QVariant::fromValue(li));
        }
        else
        {
            QString properyName = oneProperty.name();
            QString pvalue = pluginMap.value(properyName);
            pAlgParam->setProperty(oneProperty.name(), pvalue);
        }
    }

    return true;
}

bool IPluginOperator::parserCellParamChildNode(const QDomNode &node, QMap<QString, QVariant> &pluginVariantMap)
{
    if (!node.hasChildNodes())
    {
        return false;
    }

    QList<QPointF> lstPoint;
    QList<QStringList> lstStringList;
    QList<std::shared_ptr<CVV::Entity::AbstractEntity>> lstEntity;
    for (int j = 0; j < node.childNodes().size(); ++j)
    {
        auto childNode = node.childNodes().at(j);
        if ("QPointF" == childNode.nodeName())
        {
            double x = childNode.toElement().attribute("x").toDouble();
            double y = childNode.toElement().attribute("y").toDouble();
            lstPoint.append(QPointF(x, y));
        }
        else if ("QStringList" == childNode.nodeName())
        {
            QString strValue = childNode.toElement().attribute("Value");
            lstStringList.append(strValue.split(","));
        }
        else
        {
            QString strClassName = "CVV::Entity::" + childNode.nodeName();
            int id = QMetaType::type(strClassName.toStdString().c_str());
            if (id == QMetaType::UnknownType)
            {
                continue;
            }
            CVV::Entity::AbstractEntity* pEntity = static_cast<CVV::Entity::AbstractEntity*>(QMetaType::create(id));
            if (!pEntity)
            {
                continue;
            }
            QDomNamedNodeMap attrMap = childNode.toElement().attributes();
            for (int i = 0; i < attrMap.count(); ++i)
            {
                QDomAttr attr = attrMap.item(i).toAttr();
                pEntity->setProperty(attr.name().toStdString().c_str(), attr.value());
            }
            lstEntity.push_back(std::shared_ptr<CVV::Entity::AbstractEntity>(pEntity));
        }
    }

    if (!lstPoint.isEmpty())
    {
        pluginVariantMap.insert(node.nodeName(), QVariant::fromValue(lstPoint));
    }

    if (!lstStringList.isEmpty())
    {
        pluginVariantMap.insert(node.nodeName(), QVariant::fromValue(lstStringList));
    }

    if (!lstEntity.isEmpty())
    {
        pluginVariantMap.insert(node.nodeName(), QVariant::fromValue(lstEntity));
    }

    return true;
}

bool IPluginOperator::parserCellAlgorithmParamChildNode(const QDomNode &node, QMap<QString, QVariant> &pluginVariantMap)
{
    if (!node.hasChildNodes())
    {
        return false;
    }

    QList<QPointF> lstPoint;
    QList<QStringList> lstStringList;
    QList<std::shared_ptr<CVV::Entity::AbstractEntity>> lstEntity;
    for (int j = 0; j < node.childNodes().size(); ++j)
    {
        auto childNode = node.childNodes().at(j);
        if (node.childNodes().size() == 1
                 && "Point" == childNode.nodeName())
        {
            int x = childNode.toElement().attribute("x").toInt();
            int y = childNode.toElement().attribute("y").toInt();
            pluginVariantMap.insert(node.nodeName(), QPoint(x, y));
        }
        else if ("QPointF" == childNode.nodeName())
        {
            double x = childNode.toElement().attribute("x").toDouble();
            double y = childNode.toElement().attribute("y").toDouble();
            lstPoint.append(QPointF(x, y));
        }
        else if ("QStringList" == childNode.nodeName())
        {
            QString strValue = childNode.toElement().attribute("Value");
            lstStringList.append(strValue.split(","));
        }
        else
        {
            QString strClassName = "CVV::Entity::" + childNode.nodeName();
            int id = QMetaType::type(strClassName.toStdString().c_str());
            if (id == QMetaType::UnknownType)
            {
                continue;
            }
            CVV::Entity::AbstractEntity* pEntity = static_cast<CVV::Entity::AbstractEntity*>(QMetaType::create(id));
            if (!pEntity)
            {
                continue;
            }
            QDomNamedNodeMap attrMap = childNode.toElement().attributes();
            for (int i = 0; i < attrMap.count(); ++i)
            {
                QDomAttr attr = attrMap.item(i).toAttr();
                pEntity->setProperty(attr.name().toStdString().c_str(), attr.value());
            }
            lstEntity.push_back(std::shared_ptr<AbstractEntity>(pEntity));
        }
    }

    if (!lstPoint.isEmpty())
    {
        pluginVariantMap.insert(node.nodeName(), QVariant::fromValue(lstPoint));
    }

    if (!lstStringList.isEmpty())
    {
        pluginVariantMap.insert(node.nodeName(), QVariant::fromValue(lstStringList));
    }

    if (!lstEntity.isEmpty())
    {
        pluginVariantMap.insert(node.nodeName(), QVariant::fromValue(lstEntity));
    }

    return true;
}

QList<CVV::Interface::PluginDesc> IPluginOperator::getPluginDescList()
{
    QList<PluginDesc> pluginDescs;
    //1.初始化单元插件信息
    QVector<PluginSpec *> plugins = PluginManager::plugins();
    for(auto plugin : qAsConst(plugins))
    {
        PluginDesc pluginDesc;
        pluginDesc.setCode(plugin->code());
        pluginDesc.setName(plugin->name());
        pluginDesc.setVersion(plugin->version());
        pluginDesc.setCategory(plugin->category());
        pluginDesc.setCategoryIcon(plugin->categoryIcon());
        pluginDesc.setParams(plugin->params());
        pluginDesc.setIconPath(plugin->iconPath());
        pluginDesc.setDescription(plugin->description());
        pluginDescs.append(pluginDesc);
     }

    return  pluginDescs;
}

QList<FlowCellParam> IPluginOperator::getFlowCellParam(const QString &pluginCode,const QString &flowId, const QString &cellId)
{
   QList<FlowCellParam> flowCellParams;
    CVV::Interface::IPluginOperator * opt=dynamic_cast<CVV::Interface::IPluginOperator *>
            (CVV::Infrastructure::ExtensionSystem::PluginManager
             ::getObjectByName(pluginCode));

    if(opt != nullptr){
        auto dialog= opt->flowCellDialogs()[flowId][cellId];
        if(dialog != nullptr)
        {
            flowCellParams = dialog->getFlowCellParam();
        }
    }
    return  flowCellParams;
}

QList<FlowCellParam> IPluginOperator::getFlowCellAlgorithmParam(const QString &pluginCode, const QString &flowId, const QString &cellId)
{
    QList<FlowCellParam> flowCellParams;
    CVV::Interface::IPluginOperator * opt = dynamic_cast<CVV::Interface::IPluginOperator *>
            (CVV::Infrastructure::ExtensionSystem::PluginManager
             ::getObjectByName(pluginCode));

    if(opt != nullptr){
        auto dialog= opt->flowCellDialogs()[flowId][cellId];
        if(dialog!=nullptr)
        {
            flowCellParams = dialog->getFlowCellAlgorithmParam();
        }
    }
    return  flowCellParams;
}

QMap<QString, QList<FlowCellParam> > IPluginOperator::getFlowParam(const QString &pluginCode, const QString &flowId, const QString &cellId)
{
    CVV::Interface::IPluginOperator * opt=dynamic_cast<CVV::Interface::IPluginOperator *>
            (CVV::Infrastructure::ExtensionSystem::PluginManager
             ::getObjectByName(pluginCode));
    if(opt != nullptr){
        auto dialog= opt->flowCellDialogs()[flowId][cellId];
        if(dialog!=nullptr)
        {
            return dialog->getFlowParam();
        }
    }
    return  QMap<QString,QList<FlowCellParam> >();
}

IPluginParam IPluginOperator::getPluginParam(const QString &pluginCode, const QString &flowId, const QString &cellId)
{
    IPluginParam param;
    CVV::Interface::IPluginOperator * opt=dynamic_cast<CVV::Interface::IPluginOperator *>
            (CVV::Infrastructure::ExtensionSystem::PluginManager
             ::getObjectByName(pluginCode));

    if(opt != nullptr){
        auto dialog= opt->flowCellDialogs()[flowId][cellId];
        if(dialog!=nullptr)
        {
            param=*(dialog->getPluginParam());
        }
    }
    return  param;
}

void IPluginOperator::resetDialogParamRunState(const QString &pluginCode, const QString &flowId, const QString &cellId)
{
    CVV::Interface::IPluginOperator * opt=dynamic_cast<CVV::Interface::IPluginOperator *>
            (CVV::Infrastructure::ExtensionSystem::PluginManager
             ::getObjectByName(pluginCode));

    if(nullptr != opt)
    {
        auto dialog= opt->flowCellDialogs()[flowId][cellId];
        if(nullptr != dialog)
        {
            dialog->getPluginParam()->setT_status(NotRunning);
        }
    }
}

std::shared_ptr<IPluginDialog> IPluginOperator::getFlowCellDialog(const QString &pluginCode, const QString &flowId, const QString &cellId)
{
    CVV::Interface::IPluginOperator * opt = dynamic_cast<CVV::Interface::IPluginOperator *>
            (CVV::Infrastructure::ExtensionSystem::PluginManager::getObjectByName(pluginCode));

    if(opt != nullptr)
    {
        auto dialog= opt->flowCellDialogs()[flowId][cellId];
        if(dialog!=nullptr)
        {
            return dialog;
        }
    }
    return nullptr;
}

void IPluginOperator::changeLanguage(QString local)
{
    qDebug() << "IPluginOperator::changeLanguage--" << local;
    s_localName = local;
    QMap<QString, QMap<QString, std::shared_ptr<IPluginDialog>>>::const_iterator i = m_flowCellDialogs.constBegin();
    while (i != m_flowCellDialogs.constEnd())
    {
        QMap<QString, std::shared_ptr<IPluginDialog>>::const_iterator j = i.value().constBegin();
        while(j != i.value().constEnd())
        {
            j.value()->changeLanguage(local);
            ++j;
        }
        ++i;
    }

}

void IPluginOperator::createAlgorithmParam(const QString &pluginCode, const QString &flowId, const QString &cellId)
{
    if (flowId.isEmpty() || cellId.isEmpty())
    {
        return;
    }

    QString strAlgPluginCode = pluginCode + "Algorithm";        // 算法插件code
    CVV::Interface::IAlgorithmPluginOperator* pAlgOperator =
            dynamic_cast<CVV::Interface::IAlgorithmPluginOperator*>(CVV::Infrastructure::ExtensionSystem::PluginManager::getObjectByName(strAlgPluginCode));
    if (!pAlgOperator)      // 此单元cell没有算法插件
    {
        return;
    }

    pAlgOperator->initialize(flowId, cellId);
}

QHash<QString, QList<FlowCellParam> > IPluginOperator::getFlowTreeParams(const QString &flowId)
{
    QHash<QString, QList<FlowCellParam> > hashFlowTreeParam;
    if (flowId.isEmpty())
    {
        return hashFlowTreeParam;
    }

    QHash<QString, FlowTree> flowtreeMap = gFlowTreeManager->getFlowTree(flowId);
    for (auto flowtree : flowtreeMap.values())
    {
        std::shared_ptr<IPluginDialog> cell = getFlowCellDialog(flowtree.pluginCode(), flowId, flowtree.cellId());
        if (!cell)
        {
            continue;
        }

        QList<FlowCellParam> flowCellParams;
        QJsonArray aryPluginParam = gFlowTreeManager->getPluginParam(flowId, flowtree.cellId(), flowtree.pluginCode());
        for( auto param : aryPluginParam)
        {
            QJsonObject pobj = param.toObject();
            FlowCellParam fcp;
            const QMetaObject* metaObj = fcp.metaObject();
            int propertyCnt = metaObj->propertyCount();
            for ( int i = 1; i < propertyCnt; ++i )
            {
                QMetaProperty oneProperty = metaObj->property(i);
                QString properyName = oneProperty.name();
                if(properyName == "Value")
                {
                    QString code = pobj.value("Code").toString();
                    QVariant var = cell->getPluginParam()->property(code.toStdString().c_str());
                    if (var.canConvert<QList<std::shared_ptr<CVV::Entity::AbstractEntity>>>())
                    {
                        QStringList lstStr;
                        QList<std::shared_ptr<CVV::Entity::AbstractEntity>> lstValue = var.value<QList<std::shared_ptr<CVV::Entity::AbstractEntity>>>();
                        for (auto &val : qAsConst(lstValue))
                        {
                            if (!val)
                            {
                                continue;
                            }

                            QString str = val->toString();
                            if (!str.isEmpty())
                            {
                                lstStr.push_back(str);
                            }
                        }
                        lstValue.clear();
                        fcp.setValue(lstStr.join(","));
                    }
                    else
                    {
                        fcp.setValue(var.toString());
                    }
                }
                else
                {
                    QString val=pobj.value(properyName).toString();
                    fcp.setProperty(oneProperty.name(),val);
                }
            }
            fcp.setPluginCode(flowtree.pluginCode());
            fcp.setPluginId(flowtree.cellId());
            flowCellParams.append(fcp);
        }
        hashFlowTreeParam.insert(QString("%1_%2").arg(flowtree.pluginName()).arg(flowtree.cellId()), flowCellParams);
    }
    return hashFlowTreeParam;
}

bool IPluginOperator::setIPluginisModelData(const QString &pluginCode, const QString &flowId, const QString &cellId, bool isModel)
{
    IPluginParam param;
    CVV::Interface::IPluginOperator * opt=dynamic_cast<CVV::Interface::IPluginOperator *>
            (CVV::Infrastructure::ExtensionSystem::PluginManager
             ::getObjectByName(pluginCode));

    if(opt != nullptr){
        auto dialog= opt->flowCellDialogs()[flowId][cellId];
        if(dialog!=nullptr)
        {
            dialog->getPluginParam()->setIsModelData(isModel);
        }
    }
    else {
        return false;
    }
    return true;
}

void IPluginOperator::setSubprocessInputParam(const QString &flowId,
                                              const QHash<QString, QList<FlowCellParam> > &hashData,
                                              const QMap<QString, QVariant> &mapParamValue)
{
    for(auto pluginCell : CVV::Infrastructure::ExtensionSystem::PluginManager::allObjects())
    {
        CVV::Interface::IPluginOperator* opt = dynamic_cast<CVV::Interface::IPluginOperator*>(pluginCell);
        if(opt)
        {
            QMap<QString, std::shared_ptr<CVV::Interface::IPluginDialog>> mapDialog = opt->flowCellDialogs()[flowId];
            for (auto dlg : mapDialog)
            {
                if(dlg)
                {
                    dlg->setSubprocessInputParam(hashData);
                    dlg->setSubprocessParamValue(mapParamValue);
                }
            }
        }
    }
}

}
}
